use std::fmt::Debug;

#[derive(Debug)]
struct User {
    name: String,
    age: i32,
}

trait Iteratorx<T: Debug> {
    fn has_next(&self) -> bool;
    fn get_next(&mut self) -> Option<&T>;
}

trait Collection<T: Debug> {
    fn create_iterator(self) -> Box<dyn Iteratorx<T>>;
}


struct AnyIterator<T: Debug> {
    index: usize,
    items: Vec<T>,
}

impl<T: Debug> Iteratorx<T> for AnyIterator<T> {
    fn has_next(&self) -> bool {
        return self.items.len() > self.index;
    }

    fn get_next(&mut self) -> Option<&T> {
        if self.has_next() {
            let result: Option<&T> = self.items.get(self.index);
            self.index += 1;
            return result;
        }
        return None;
    }
}

struct UserCollection {
    items: Vec<User>,
}

impl UserCollection {
    fn create_iterator(self) -> Box<dyn Iteratorx<User>> {
        Box::new(AnyIterator { index: 0, items: self.items })
    }
}

#[test]
fn text() {
    let collection = UserCollection {
        items: vec![
            User { name: "name1".to_string(), age: 1 },
            User { name: "name2".to_string(), age: 2 },
            User { name: "name3".to_string(), age: 3 },
            User { name: "name4".to_string(), age: 4 },
        ],
    };
    let mut x = collection.create_iterator();
    println!("{:?}", x.get_next());
    println!("{:?}", x.get_next());
    println!("{:?}", x.get_next());
    println!("{:?}", x.get_next());
    println!("{:?}", x.get_next());

    let mut collection = AnyIterator {
        index: 0,
        items: vec![1, 2, 3],
    };

    println!("{:?}", collection.get_next());
    println!("{:?}", collection.get_next());
    println!("{:?}", collection.get_next());
    println!("{:?}", collection.get_next());
}